home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / USBSampleStorageDriver / UnitTableDriver / UnitTableFloppySupport.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  11.6 KB  |  473 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        UnitTableFloppySupport.c
  3.  
  4.     Contains:    All floppy disk specific functionality
  5.  
  6.     Version:    1.0
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11. #include <DriverServices.h>
  12. #include <Errors.h>
  13.  
  14. #include "UnitTableFloppySupport.h"
  15. #include "UnitTableDeviceAccess.h"
  16. #include "UnitTableDriveQSupport.h"
  17. #include "UnitTableCWDefines.h"
  18.  
  19. typedef struct FloppyRequestPB
  20. {
  21.     UInt32                            userData;
  22.     ControlStatusCompletionProcPtr     completionProc;
  23. } FloppyRequestPB, *FloppyRequestPBPtr;
  24.  
  25.  
  26. static DriveQRecPtr            gFloppyDrive = nil;
  27. static FloppyRequestPB        gFloppyInternalDrivePB;
  28.  
  29. static OSStatus     FormatFloppyDisk(FloppyRequestPB *drivePB);
  30. static OSStatus     VerifyFloppyDisk( FloppyRequestPB *drivePB );
  31. static OSStatus     FormatAndWriteFloppyImage( CntrlParamPtr pbPtr );
  32. static OSStatus        GetFloppyFormatList( CntrlParamPtr pbPtr );
  33.  
  34. static volatile    OSStatus    gInternalReadWriteErr;
  35. static void     InternalReadWriteCompletion(  UInt32 userData, OSStatus status );
  36.  
  37. void ResetFloppyDriveQueue( DriveQRecPtr floppyDriveQ )
  38. {
  39.     DrvSts    *theDriveStatus;
  40.     
  41.     theDriveStatus = (DrvSts *) &floppyDriveQ->driveStatus;
  42.  
  43.     theDriveStatus->track         = 80;            // Sectors on a MFM disk
  44.     theDriveStatus->writeProt     = 0;            // not write protected yet
  45.     theDriveStatus->diskInPlace = 0;            // Ejectable Disk
  46.     theDriveStatus->installed     = 1;            // drive is installed
  47.     theDriveStatus->sides         = -1;            // -1 means double sided floppy
  48.     theDriveStatus->qType         = 0;            // neither dQDrvSz and dQDrvSz2 are used
  49.     theDriveStatus->dQFSID         = 0;            // File Manager's volume type
  50.     theDriveStatus->twoSideFmt     = -1;            /* after 1st rd/wrt: 0=1 side, -1=2 side */
  51.     theDriveStatus->needsFlush     = -1;            /* -1 for MacPlus drive */
  52.     theDriveStatus->diskErrs     = 0;            /* soft error count */
  53. }
  54.  
  55. DriveQRecPtr GetFloppyDriveRec( void )
  56. {
  57.     return gFloppyDrive;
  58. }
  59.  
  60. Boolean IsDriveAFloppy( SInt16 driveRefNum )
  61. {
  62.     if (gFloppyDrive == nil )
  63.     {
  64.         return false;
  65.     }
  66.     
  67.     if ( gFloppyDrive->driveNum == driveRefNum )
  68.     {
  69.         return true;
  70.     }
  71.     else
  72.     {
  73.         return false;
  74.     }
  75. }
  76.  
  77. OSStatus SetupFloppyStructures( SInt16 theDrvrRefNum )
  78. {
  79.     gFloppyDrive = GetNewDriveQRec();
  80.     
  81.     ResetFloppyDriveQueue( gFloppyDrive );
  82.  
  83.     gFloppyDrive->deviceType = kdgFloppyType;
  84.     gFloppyDrive->isFloppy = true;
  85.     gFloppyDrive->isValidRecord = false;
  86.     gFloppyDrive->isPermanentQElement = true;
  87.     
  88.     if( IsDriveQueueNumberFree( 1 ) == true )
  89.     {
  90.         // Drive queue element 1 is free, use it
  91.         gFloppyDrive->driveNum = 1;                    // assign a logical drive number
  92.     }
  93.     else if( IsDriveQueueNumberFree( 2 ) == true )
  94.     {
  95.         // Drive queue element 2 is free, use it
  96.         gFloppyDrive->driveNum = 2;                    // assign a logical drive number
  97.     }
  98.     else
  99.     {
  100.         gFloppyDrive->driveNum = NextQDrive();        // assign a logical drive number
  101.     }
  102.     
  103.     NativeAddDrive(theDrvrRefNum, gFloppyDrive->driveNum, (DrvQElPtr)  &gFloppyDrive->driveStatus.qLink);
  104.  
  105.     return noErr;
  106. }
  107.  
  108. OSStatus RemoveFloppyStructures( void )
  109. {
  110.     if ( gFloppyDrive != nil )
  111.     {
  112.         // If we installed a floppy drive Queue, remove it.
  113.         RemoveDrive( gFloppyDrive );
  114.     }
  115.     
  116.     return noErr;
  117. }
  118.  
  119. OSStatus FloppyControlCallSupport(     UInt32                                    userData,
  120.                                     CntrlParamPtr                            cntrlPBPtr,
  121.                                     ControlStatusCompletionProcPtr            callBack )
  122. {
  123.     OSStatus        err            = noErr;
  124.     SInt16            driveNum;
  125.  
  126.     BlockZero((Ptr) &gFloppyInternalDrivePB, sizeof(FloppyRequestPB));
  127.     
  128.     gFloppyInternalDrivePB.userData         = userData;
  129.     gFloppyInternalDrivePB.completionProc     = callBack;
  130.  
  131.     driveNum = cntrlPBPtr->ioVRefNum;
  132.     
  133.     // Parse the control codes…
  134.     switch( cntrlPBPtr->csCode ) 
  135.     {
  136.         case kVerify:                        // Verify the media, this should only be called for floppies
  137.         {
  138.             err = VerifyFloppyDisk( &gFloppyInternalDrivePB );
  139.         }
  140.         break;
  141.  
  142.         case kFormat:
  143.         {
  144.             err = FormatFloppyDisk( &gFloppyInternalDrivePB );
  145.         }
  146.         break;
  147.         
  148.         case kSetTagBuffer:                    // This is a floppy specific control call
  149.         {            
  150.             err = controlErr;                // Return a controlErr, since we do not support this call
  151.         }
  152.         break;
  153.  
  154.         case kTrackCache:                    // This is a floppy specific control call
  155.         {            
  156.             err = noErr;                    // The driver does not keep an internal write cache,
  157.                                             // therefore, it will act like it does and return noErr
  158.         }
  159.         break;
  160.  
  161.         case kDriveInfo:                    // DRIVE INFO request (was from ATA maanger)
  162.         {
  163.             // If we currently have a floppy loaded, return the following info
  164.             cntrlPBPtr->csParam[1] =     ( 1 << 11 )     // Drive cardinality (0 - primary, 1 - secondary)
  165.                                 |    ( 0 << 10 )        // Media removability ( 0 - removable, 1 - fixed )
  166.                                 |     ( 0 << 9 )         // Interface ( 0 - floppy, 1 - SCSI )        
  167.                                 |     ( 1 << 8 )         // Location ( 0 - internal, 1 - external )
  168.                                                     // Bits 4,5,6,7 are reserved
  169.                                 |     4;                // Drive Type ( use 4 for SuperDrive for compatibility )
  170.         }
  171.         break;
  172.  
  173.         // Floppy specific call to support the DiskCopy Format and Write Image function
  174.         case kDiskCopy:
  175.         {
  176.             err = FormatAndWriteFloppyImage( cntrlPBPtr );
  177.         }
  178.         break;
  179.  
  180.         default:
  181.         {
  182.             err = controlErr;
  183.         }
  184.         break;
  185.     }
  186.     
  187.     return err;
  188. }
  189.  
  190. OSStatus FloppyStatusCallSupport(     UInt32                                    userData,
  191.                                     CntrlParamPtr                            cntrlPBPtr,
  192.                                     ControlStatusCompletionProcPtr            callBack )
  193. {
  194.     OSStatus        err    = noErr;
  195.     SInt16            driveNum;
  196.  
  197.     BlockZero((Ptr) &gFloppyInternalDrivePB, sizeof(FloppyRequestPB));
  198.     gFloppyInternalDrivePB.userData         = userData;
  199.     gFloppyInternalDrivePB.completionProc     = callBack;
  200.  
  201.     driveNum = cntrlPBPtr->ioVRefNum;
  202.     
  203.     // Parse the control codes…
  204.     switch(cntrlPBPtr->csCode) 
  205.     {
  206.         case kReturnFormatList:
  207.         {
  208.             err = GetFloppyFormatList( cntrlPBPtr );
  209.         }
  210.         break;
  211.  
  212.         case kMFMStatus:
  213.         {
  214.             cntrlPBPtr->csParam[0] = -3;                        // PC Industry standard MFM (no GCR support)
  215.             
  216.             // Check to see if there is a floppy disk mounted
  217.             if(GetFloppyDriveRec()->capacity != 0)
  218.             {
  219.                 cntrlPBPtr->csParam[1] = -1;                    // MFM Disk installed
  220.                 
  221.                 if( GetFloppyDriveRec()->capacity < 0x600 )
  222.                 {
  223.                     cntrlPBPtr->csParam[2] = 0;                    // 720K MFM Disk installed
  224.                 }
  225.                 else
  226.                 {
  227.                     cntrlPBPtr->csParam[2] = -1;                // 1.44M MFM Disk installed
  228.                 }
  229.             }
  230.             else
  231.             {
  232.                 cntrlPBPtr->csParam[1] = 0;                        // No disk installed
  233.                 cntrlPBPtr->csParam[2] = 1;                        // No disk installed
  234.             }
  235.             
  236.             cntrlPBPtr->csParam[3] = -5;                        // Generic PC Floppy Disk Controller
  237.             
  238.             err = noErr;
  239.         }
  240.         break;
  241.     
  242.         case kDuplicatorVersion:                                // DiskCopy version supported
  243.         {
  244.             cntrlPBPtr->csParam[0] = 0x0410;                    // We support the Diskcopy 4.1 API
  245.             err = noErr;
  246.         }
  247.         break;
  248.         
  249.         default:
  250.         {
  251.             err = statusErr;
  252.         }
  253.         break;
  254.     }
  255.     
  256.     return err;
  257. }
  258.  
  259. OSStatus VerifyFloppyDisk( FloppyRequestPB *drivePB )
  260. {
  261.     UInt16         diskCapacity;
  262.     UInt16         startBlock;
  263.     UInt16        numberBlocks = 16;
  264.     UInt8        *blockBuffer;
  265.     OSStatus    err;
  266.     DriveQRec    *theDrive = gFloppyDrive;
  267.     
  268.     diskCapacity = theDrive->capacity;
  269.     blockBuffer = (UInt8 *) NewPtrSysClear(numberBlocks * theDrive->blockSize);
  270.     if(blockBuffer == nil)
  271.     {
  272.         err = verErr;
  273.     }
  274.     else
  275.     {
  276.         for (startBlock = 0; startBlock<diskCapacity; startBlock+=numberBlocks)
  277.         {    
  278.             err = ReadWriteSingleBuffer(    (UInt32) drivePB,
  279.                                             startBlock,
  280.                                             numberBlocks,
  281.                                             (Ptr)  blockBuffer,
  282.                                             (numberBlocks * theDrive->blockSize),
  283.                                             false,
  284.                                             &InternalReadWriteCompletion );
  285.  
  286.             gInternalReadWriteErr = err;
  287.             
  288.             while ( err == 1 )
  289.             {
  290.                 err = gInternalReadWriteErr;
  291.             }
  292.             
  293.             // an Error has occured                    
  294.             if ( err != noErr )
  295.             {
  296.                 // report a verify error
  297.                 err = verErr;
  298.             }
  299.         }
  300.         
  301.         DisposePtr((Ptr) blockBuffer);
  302.     }
  303.     
  304.     return err;
  305. }
  306.  
  307. OSStatus FormatAndWriteFloppyImage( CntrlParamPtr pbPtr )
  308. {
  309.     UInt16        theFormat;
  310.     UInt8        *theDiskImage;
  311.     OSStatus     err;
  312.     DriveQRec     *theDrive = gFloppyDrive;
  313.     
  314.     if( theDrive->isWriteProtected == true)
  315.     {
  316.         return wPrErr;            // disk is write protected
  317.     }
  318.             
  319.     theFormat = pbPtr->csParam[0];
  320.     theDiskImage = (UInt8 *) *((UInt32 *) &pbPtr->csParam[1]);        // Extract the pointer to the data
  321.     
  322.     err = ReadWriteSingleBuffer(    (UInt32) nil,
  323.                                     0,
  324.                                     theDrive->capacity,
  325.                                     (Ptr)  theDiskImage,
  326.                                     (theDrive->capacity * theDrive->blockSize),
  327.                                     true,
  328.                                     &InternalReadWriteCompletion );
  329.  
  330.     gInternalReadWriteErr = err;
  331.     while ( err == 1 )
  332.     {
  333.         err = gInternalReadWriteErr;
  334.     }
  335.  
  336.     // an Error has occured                    
  337.     if ( err != noErr )
  338.     {
  339.         // report an error
  340.         err = paramErr;
  341.     }
  342.     
  343.     return err;
  344. }
  345.  
  346. OSStatus GetFloppyFormatList( CntrlParamPtr pbPtr )
  347. {
  348.     typedef struct FormatList
  349.     {
  350.         UInt32        NumberBlock;
  351.         UInt8        TSSValid         : 1;
  352.         UInt8        IsCurrentFormat : 1;
  353.         UInt8        CanFormat        : 1;
  354.         UInt8        Density            : 1;
  355.         UInt8        NoSides            : 4;
  356.         UInt8        SecPerTrack;
  357.         UInt16        NumberTracks;
  358.     } FormatList;
  359.     
  360.     DriveQRec         *theDrive;
  361.     UInt8            returnNumber;
  362.     UInt8            totalFormats = 2;
  363.     FormatList        theFormats[2];
  364.     
  365.     theDrive = gFloppyDrive;
  366.     
  367.     // Setup the Formats
  368.     // Double Density Floppy Disk
  369.     theFormats[0].NumberBlock        = 1440;
  370.     theFormats[0].TSSValid            = 1;
  371.     theFormats[0].Density            = 0;            // 0 means single density, 1 means Double Density
  372.     theFormats[0].NoSides            = 2;
  373.     theFormats[0].SecPerTrack        = 9;
  374.     theFormats[0].NumberTracks        = 80;
  375.     
  376.     // High Density Floppy Disk
  377.     theFormats[1].NumberBlock        = 2880;
  378.     theFormats[1].TSSValid            = 1;
  379.     theFormats[1].Density            = 1;
  380.     theFormats[1].NoSides            = 2;
  381.     theFormats[1].SecPerTrack        = 18;
  382.     theFormats[1].NumberTracks        = 80;
  383.  
  384.     if( theDrive->capacity == 0 )
  385.     {
  386.         // Ther is currently no disk mounted
  387.         theFormats[0].CanFormat            = 1;        // 1 means we can not format this disk as 720K
  388.         theFormats[1].CanFormat            = 1;        // 1 means we can not format this disk as 1.44M
  389.         theFormats[0].IsCurrentFormat    = 0;         // 0 means 720K MFM Disk is not installed
  390.         theFormats[1].IsCurrentFormat     = 0;        // 0 means 1.44M MFM Disk is not installed
  391.     }
  392.     else if( theDrive->capacity < 0x600 )
  393.     {
  394.         theFormats[0].CanFormat            = 0;        // 0 means we can format this disk as 720K
  395.         theFormats[1].CanFormat            = 1;        // 1 means we can not format this disk as 1.44M
  396.         theFormats[0].IsCurrentFormat    = 1;         // 1 means 720K MFM Disk is installed
  397.         theFormats[1].IsCurrentFormat     = 0;        // 0 means 1.44M MFM Disk is not installed
  398.     }
  399.     else
  400.     {
  401.         theFormats[0].CanFormat            = 1;        // 1 means we can not format this disk as 720K
  402.         theFormats[1].CanFormat            = 0;        // 0 means we can format this disk as 1.44M
  403.         theFormats[0].IsCurrentFormat    = 0;         // 0 means 720K MFM Disk is not installed
  404.         theFormats[1].IsCurrentFormat     = 1;        // 1 means 1.44M MFM Disk is installed
  405.     }
  406.  
  407.     returnNumber = *((UInt16 *) &pbPtr->csParam[0]);
  408.     if( totalFormats < returnNumber )
  409.     {
  410.         returnNumber = totalFormats;
  411.     }
  412.     
  413.     BlockCopy( (Ptr) &theFormats[0], (Ptr) (*((UInt32 *) &pbPtr->csParam[1])), sizeof(FormatList) * returnNumber);
  414.     *((UInt16 *) &pbPtr->csParam[0]) = returnNumber;
  415.     
  416.     return noErr;
  417. }
  418.  
  419.  
  420. void InternalReadWriteCompletion(  UInt32 userData, OSStatus status )
  421. {
  422. #pragma unused ( userData )
  423.     gInternalReadWriteErr = status;
  424. }
  425.  
  426. #pragma mark -
  427. #pragma mark Format Routines
  428. static void     FormatFloppyCompletion ( UInt32 userData, OSStatus    status );
  429.  
  430. OSStatus FormatFloppyDisk(FloppyRequestPB *drivePB)
  431. {
  432.     UInt32         TotalBlocksOnMedia, BlockLengthInBytes;
  433.     Boolean        IsWriteProtected;
  434.     OSType        currentType;
  435.     
  436.     GetMediaProperties( &TotalBlocksOnMedia, &BlockLengthInBytes, &IsWriteProtected, ¤tType );
  437.     return FormatMedia(    (UInt32) drivePB,
  438.                         TotalBlocksOnMedia,
  439.                         BlockLengthInBytes,
  440.                         FormatFloppyCompletion );    
  441. }
  442.  
  443. void FormatFloppyCompletion(    UInt32        userData,
  444.                                 OSStatus    status )
  445. {
  446.     OSStatus                 err = status;
  447.     DriveQRec                *drive;
  448.     FloppyRequestPB            *drivePB = (FloppyRequestPB *) userData;
  449.  
  450.     drive = gFloppyDrive;
  451.  
  452.     if (err == noErr) 
  453.     {
  454.         Boolean    isWriteProtected;
  455.         OSType    currentType;
  456.         
  457.         GetMediaProperties( &drive->capacity,  &drive->blockSize, &isWriteProtected, ¤tType ); 
  458.         if ((drive->capacity == 0) || (drive->blockSize == 0))
  459.         {
  460.             // The format has failed, inform the OS
  461.             err = controlErr;
  462.         }
  463.     }
  464.     else
  465.     {
  466.         // The format has failed, inform the OS
  467.         err = controlErr;
  468.     }
  469.     
  470.     (*drivePB->completionProc)( drivePB->userData, err );
  471. }
  472.  
  473.